from typing import List, Optional
from uuid import UUID

from fastapi_template.models import Role

from .dto import RoleCreateDTO, RoleDTO, RoleUpdateDTO
from .facade import RoleFacade


class RoleFacadeImpl(RoleFacade):
    """Implementation of the role domain facade."""

    async def create_role(self, role_data: RoleCreateDTO) -> RoleDTO:
        """Create a new role."""
        role = await Role.create(name=role_data.name,
                                 description=role_data.description,
                                 parent_role_id=role_data.parent_role_id)
        return RoleDTO.model_validate(role)

    async def get_role_by_id(self, role_id: UUID) -> Optional[RoleDTO]:
        """Get role by ID."""
        role = await Role.get_or_none(id=role_id)
        return RoleDTO.model_validate(role) if role else None

    async def get_role_by_name(self, name: str) -> Optional[RoleDTO]:
        """Get role by name."""
        role = await Role.get_or_none(name=name)
        return RoleDTO.model_validate(role) if role else None

    async def get_all_roles(self) -> List[RoleDTO]:
        """Get all roles."""
        roles = await Role.all()
        return [RoleDTO.model_validate(role) for role in roles]

    async def update_role(self, role_id: UUID,
                          role_data: RoleUpdateDTO) -> Optional[RoleDTO]:
        """Update role information."""
        role = await Role.get_or_none(id=role_id)
        if not role:
            return None

        update_data = role_data.model_dump(exclude_unset=True)
        if update_data:
            await role.update_from_dict(update_data).save()

        return RoleDTO.model_validate(role)

    async def delete_role(self, role_id: UUID) -> bool:
        """Delete role by ID."""
        role = await Role.get_or_none(id=role_id)
        if not role:
            return False
        await role.delete()
        return True

    async def get_child_roles(self, role_id: UUID) -> List[RoleDTO]:
        """Get all child roles of a role."""
        roles = await Role.filter(parent_role_id=role_id)
        return [RoleDTO.model_validate(role) for role in roles]
